/*
	@file: log/source/LogRunner.cpp
	@author: Wolfhead
 */

#include "LogRunner.h"
#include <vector>
#include <boost/foreach.hpp>

namespace logger
{

LogRunner::LogRunner(const LogOption& option)
	: m_option(option)
	, m_queue(option.queue_buffer) 
{
	set_option(option);
}

LogRunner::~LogRunner()
{
	stop();
}

void LogRunner::set_option(const LogOption& option)
{
	m_option = option;

	m_queue.set_limit(m_option.queue_buffer);
}

const LogOption& LogRunner::get_option()
{
	return m_option;
}

int LogRunner::start()
{
	if (m_thread_ptr)
	{
		return 0;
	}

	m_running = true;
	m_thread_ptr = boost::shared_ptr<boost::thread>(
		new boost::thread(boost::bind(&LogRunner::run, shared_from_this())));

	return 0;
}

int LogRunner::stop()
{
	m_running = false;
	if (m_thread_ptr)
	{	
		m_thread_ptr->join();
		m_thread_ptr = boost::shared_ptr<boost::thread>();
	}

	return 0;
}

int LogRunner::restart()
{
	stop();
	start();

	return 0;
}

int LogRunner::run_once()
{
    SpliteQueue split_queue;
    m_queue.split(split_queue);

    if (!split_queue.empty() && m_option.logger_ptr)
    {
		if (m_option.formatter_ptr && m_option.backend_format)
		{    	
			std::string message;
			for (typename SpliteQueue::iterator it = split_queue.begin();
				 it != split_queue.end();
				 ++it)
	    	{
				message.clear();
				m_option.formatter_ptr->format(*it, message);
				(*it)->message = message;      		
	    	}
    	}

        m_option.logger_ptr->log(split_queue);

        if (m_option.auto_flush)
        {
        	m_option.logger_ptr->flush();
    	}

    	return split_queue.size();
    }
    else
    {
    	return 0;
    }
}

int LogRunner::run()
{    
    do
    {
    	if (0 == run_once())
    	{
			boost::this_thread::sleep(
				boost::posix_time::milliseconds(1));    		
    	}

    } while (m_running);

    // flush all that left into logger
    run_once();

    return 0;
}

int LogRunner::log(LogDataPtr data_ptr)
{
	if (m_running && (data_ptr->by_name || data_ptr->priority & m_option.priority))
	{			
		m_queue.push(data_ptr);
	}

	return 0;
}

}//namespace logger
